# import bpy
# from mathutils import Vector
from bpy.types import PropertyGroup, Context
# from ....libs.functions.basics import set_active_object
from ....libs.functions.get_common_vars import get_common_vars
from bpy.props import IntProperty, FloatProperty, BoolProperty, EnumProperty, PointerProperty
from ..updaters.props_update_particles import particles_props_update
# from ....properties.lists.updaters.props_update_particles import ui_update
from .anim.props_emission_anim import ActiveEmitterEmissionAnimProps


class ActiveEmitterEmissionProps(PropertyGroup):

    """ Propiedades guardadas en el active_emitter_item.emission.x """

    # estas van a nivel emitter item:
    anim: PointerProperty(type=ActiveEmitterEmissionAnimProps)

    emit_from: EnumProperty(
        items=[
            ('VERT', "Vertices", "", 0),
            ('FACE', "Faces", "", 1),
            ('VOLUME', "Volume", "", 2),
        ],
        default='VOLUME',
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "emit_from")
    )

    grid_resolution: IntProperty(
        name="Resolution",
        description="Resolution that will directly influence the amount of particles to use",
        default=20,
        min=2,
        # soft_max=50,
        soft_max=100,
        max=250,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "grid_resolution")
    )
    
    # INFLOW:

    # Para poder decirle x numero de particulas por cara, por frame (esto va bien si emites con un plano):
    def count_or_resolution_update(self, context):

        fluid_groups = get_common_vars(context, get_fluid_groups=True)
        active_group = fluid_groups.active

        active_emitter_item = active_group.emitters.active
        if active_emitter_item is None:
            return

        prop_section = "global_mode_emission_sect"

        global_mode = getattr(active_emitter_item.switchers, prop_section)

        if global_mode:
            # Es Global:
            all_emitters_items =  [emitter_item for emitter_item in active_group.emitters.get_all_items if getattr(emitter_item.switchers, prop_section)]
        else:
            # Es local:
            all_emitters_items = [active_emitter_item]

        # print("all_emitters_items", all_emitters_items)

        #------------------------------------------------------------------------------------
        if self.count_or_resolution == 'COUNT':
            
            if self.prev_count >= 0:
                active_emitter_item.emission.count = self.prev_count
            
            else:
                active_emitter_item.emission.count = self.count

            # Les ponemos el Source > Particles/Face a 0 al hacer click en count
            for emitter_item in all_emitters_items:

                emitter_ob = next((ob for ob in emitter_item.group_coll.objects if ob.fluidlab.id_name == "Emitter_"+ emitter_item.id_name ), None)
                if not emitter_ob:
                    continue

                # Particle System Active:
                psys = emitter_ob.particle_systems.active
                psys.settings.userjit = 0

        elif self.count_or_resolution == 'RESOLUTION':
            active_emitter_item.emission.inflow_resolution = self.inflow_resolution
        #------------------------------------------------------------------------------------

        # Sync los count_or_resolutions al darle al count_or_resolutions:
        for emitter_item in all_emitters_items:
            if emitter_item.emission.count_or_resolution != active_emitter_item.emission.count_or_resolution:
                emitter_item.emission.count_or_resolution = active_emitter_item.emission.count_or_resolution

        # ui_update(context, active_emitter_item, without_self_ob=True, subsection='EMISSION')

    count_or_resolution: EnumProperty(
        items=[
            ('COUNT',       "Count",        "", 0),
            ('RESOLUTION',  "Resolution",   "", 1),
        ], 
        default='COUNT',
        update=count_or_resolution_update
    )
    inflow_resolution: IntProperty(
        name="Inflow Resolution",
        description="The number of particles that will be emitted per face, per frame",
        default=100,
        min=0,
        max=1000,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "inflow_resolution")
    )
    # Guardo el count previo para luego poder restaurarlo:
    prev_count: IntProperty(
        name="Count",
        description="Total particles emitted over the entire timeline",
        default=-999999999,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "prev_count")
    )
    count: IntProperty(
        name="Count",
        description="Total particles emitted over the entire timeline",
        default=25000,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "count")
    )
     # Para poder setar en creation 0.05 el size por defecto guardamos los valors que setee el usuario en prev_size:
    prev_size: FloatProperty(
        name="Size",
        default=-999999999,
        min=0,
        max=1000,
        unit='LENGTH',  # Especifica que la unidad es de longitud
        subtype='DISTANCE',  # Subtipo de distancia
    )
    size: FloatProperty(
        name="Size",
        default=0.05,
        min=0,
        max=1000,
        unit='LENGTH',  # Especifica que la unidad es de longitud
        subtype='DISTANCE',  # Subtipo de distancia
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "particle_size")
    )
    size_random: FloatProperty(
        name="Size Random",
        description="Render Scale Random",
        min=0,
        max=1,
        default=0, 
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "size_random")
    )
    use_emit_random: BoolProperty(
        name="Random Order",
        default=True,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "use_emit_random")
    )
    use_even_distribution: BoolProperty(
        name="Even Distribution",
        default=True,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "use_even_distribution")
    )
    frame_start: FloatProperty(
        name="Frame Start",
        default=1, 
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "frame_start")
    )
    frame_end: FloatProperty(
        name="Frame End",
        default=250, 
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "frame_end")
    )
    lifetime: FloatProperty(
        name="Lifetime",
        description="Life span of the particles",
        min=0,
        max=10000000,
        default=250, 
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "lifetime")
    )
    lifetime_random: FloatProperty(
        name="Random",
        description="Give the particle life a random variation",
        min=0,
        max=1,
        default=0, 
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "lifetime_random")
    )
    use_modifier_stack: BoolProperty(
        name="Use Modifier Stack",
        default=False,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "use_modifier_stack")
    )
    show_unborn: BoolProperty(
        name="Unborn",
        description="Show particles before they are emitted",
        default=False,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "show_unborn")
    )
    grid_random: FloatProperty(
        name="Random",
        default=0, 
        min=0, 
        max=1,
        update=lambda self, context: particles_props_update(self, context, "global_mode_emission_sect", "grid_random")
    )


    # ---------------------------------------------------------------------------------------------------

    distribution_toggle: BoolProperty(name="Distribution", default=False)

    # Para guardar el valor previo de fluid radius y poder luego restaurarlo:
    prev_fluid_radius: FloatProperty(
                                        default=1.350,
                                        min=0, 
                                        soft_max=2,
                                        max=20,
                                    )

    #--------------------------------------------------------------------------------------------------
    # Soft Start:
    #--------------------------------------------------------------------------------------------------
    
    def soft_start_update(self, context:Context) -> None:
    
        scn, fluid_groups = get_common_vars(context, get_scn=True, get_fluid_groups=True)
    
        active_group = fluid_groups.active
        emitters_list = active_group.emitters
        emitter_ob = emitters_list.get_current_emitter

        p_active = emitter_ob.particle_systems.active
        p_settings = p_active.settings

        # Sugiero el current frame:
        self.ss_frame_start = scn.frame_current

        # Si es activado:
        if self.soft_start:
           
            # Guardamos el valor previo de fluid_radius:
            self.prev_fluid_radius = p_settings.fluid.fluid_radius

            # Lo seteamos a 1.350:
            self.fluid_radius = 1.350

        else: # Si es desactivado:
           
            # Restauramos el valor previo:
            self.fluid_radius = self.prev_fluid_radius

    soft_start: BoolProperty(
                                name="Soft Start", 
                                default=False, 
                                update=soft_start_update
                            )

    ss_frame_start: IntProperty(default=1)
    
    fluid_radius_animed: BoolProperty(default=False)
    fluid_radius: FloatProperty(
                                    default=1.350,
                                    min=0, 
                                    soft_max=2,
                                    max=20,
                                )

    #--------------------------------------------------------------------------------------------------
    # End Soft Start.
    #--------------------------------------------------------------------------------------------------

    #--------------------------------------------------------------------------------------------------
    # Soft End:
    #--------------------------------------------------------------------------------------------------
    def soft_end_update(self, context):
        
        scn, fluid_groups = get_common_vars(context, get_scn=True, get_fluid_groups=True)

        if self.soft_end:
    
            # Sugiero el current frame:
            self.se_frame_start = scn.frame_current
    
            # seteo el amount con lo q tenga el damping:
            active_group = fluid_groups.active
            emitters_list = active_group.emitters
            emitter_ob = emitters_list.get_current_emitter

            p_active = emitter_ob.particle_systems.active
            p_settings = p_active.settings

            self.se_amount = p_settings.damping


    soft_end: BoolProperty(name="Soft End", default=False, update=soft_end_update)
    se_frame_start: IntProperty(default=100)
    se_duration: IntProperty(default=100)
    se_amount: FloatProperty(default=0.6, min=0, max=1)
    #--------------------------------------------------------------------------------------------------
    # End Soft End.
    #--------------------------------------------------------------------------------------------------


    normal_factor: FloatProperty(
        name="Normal",
        description="Let the surface normal give the particle a starting velocity",
        default=0,
        soft_min=0,
        soft_max=100,
        min=-1000,
        max=1000,
        precision=2,
        unit='VELOCITY',
        update=lambda self, context: particles_props_update(self, context, "global_mode_velocity_sect", "normal_factor")
    )

    object_factor: FloatProperty(
        name="Object Velocity",
        description="Let the object give the particle a starting velocity",
        default=0,
        soft_min=-1,
        soft_max=1,
        min=-200.0,
        max=200.0,
        precision=3,
        update=lambda self, context: particles_props_update(self, context, "global_mode_velocity_sect", "object_factor")
    )

    #--------------------------------------------------------------------------------------
    # Object Align Factor:
    #--------------------------------------------------------------------------------------
    oa_name = "Object Aligned"
    oa_description = "Let the emitter object give the particle a starting velocity"
    oa_default=0
    oa_soft_min=-100
    oa_soft_max=100
    oa_min=-200
    oa_max=200
    oa_precision=2
    oa_unit='VELOCITY'

    object_align_factor_x: FloatProperty(
        name=oa_name,
        description=oa_description,
        default=oa_default,
        soft_min=oa_soft_min,
        soft_max=oa_soft_max,
        min=oa_min,
        max=oa_max,
        precision=oa_precision,
        unit=oa_unit,
        update=lambda self, context: particles_props_update(self, context, "global_mode_velocity_sect", "object_align_factor_x")
    )
    object_align_factor_y: FloatProperty(
        name=oa_name,
        description=oa_description,
        default=oa_default,
        soft_min=oa_soft_min,
        soft_max=oa_soft_max,
        min=oa_min,
        max=oa_max,
        precision=oa_precision,
        unit=oa_unit,
        update=lambda self, context: particles_props_update(self, context, "global_mode_velocity_sect", "object_align_factor_y")
    )
    object_align_factor_z: FloatProperty(
        name=oa_name,
        description=oa_description,
        default=oa_default,
        soft_min=oa_soft_min,
        soft_max=oa_soft_max,
        min=oa_min,
        max=oa_max,
        precision=oa_precision,
        unit=oa_unit,
        update=lambda self, context: particles_props_update(self, context, "global_mode_velocity_sect", "object_align_factor_z")
    )
    #--------------------------------------------------------------------------------------
    # End Object Align Factor.
    #--------------------------------------------------------------------------------------

    display_color: EnumProperty(
        name="Display",
        description="Display additional data as color",
        items = [
            ('MATERIAL',        "Material",     "", 0),
            ('VELOCITY',        "Velocity",     "", 1),
            ('ACCELERATION',    "Acceleration", "", 2)
        ],
        default='VELOCITY',
        update=lambda self, context: particles_props_update(self, context, "global_mode_viewport_display_sect", "display_color")
    )


    def get_default_properties(self, target_prop):
        for prop in self.bl_rna.properties:
            if prop.identifier == target_prop:
                if hasattr(prop, "default"):
                    return prop.default